'''SUI Base'''
ident = '$Id: base.py 141 2006-08-01 19:15:43Z ahmad $'
import sys, wx, wx.calendar, rex, common, images, re, icon_manager, copy, about, editors #, traceback
from xml.dom				import minidom
import about
import webbrowser

class editor( wx.Panel ):
	'''The base user interface for rex objects.
	'''
	def __init__( self, account, rex_object, treeitem ):
		wx.Panel.__init__( self, account.window.ebook, -1, style=wx.NO_BORDER )
		self.account		= account
		self.rex_object		= rex_object
		self.rex_object.editor = self
		self.treeitem 		= treeitem
		self.parent_tree	= 0
		self.dirty			= False
		self.current_variable_editor = None
		# default sash pos
		self.sash_pos		= 150
		self.variables		= {}
		self.variable_editors = []
		self.switching		= False
		# Take care of the status bar and the menu bar
		#self.create_context_menu()
		# Set the close event for this frame
		self.Bind( wx.EVT_KEY_DOWN, self.OnKeyDown )
		self.Bind( wx.EVT_TIMER, self.OnTimer )
		self.sizer = wx.BoxSizer( wx.VERTICAL )
		# the toolbar
		self.create_toolbar()
		self.vSplitter = wx.SplitterWindow( self, -1 ) #, style=wx.SP_3DSASH | wx.SP_NOBORDER )
		self.vSplitter.Bind( wx.EVT_SPLITTER_SASH_POS_CHANGED, self.OnSashChanged )
		self.sizer.Add( self.vSplitter, 1, wx.EXPAND )
		self.var_list= wx.ListCtrl( self.vSplitter, -1, style=wx.LC_SINGLE_SEL | wx.LC_REPORT | wx.LC_NO_HEADER )
		# Create the column header
		info = wx.ListItem()
		info.m_mask = wx.LIST_MASK_TEXT # | wx.LIST_MASK_IMAGE | wx.LIST_MASK_FORMAT
		info.m_image = -1
		info.m_format = 0
		info.m_text = "Variable"
		self.var_list.InsertColumnInfo(0, info)
		# Set the events
		#.Bind( wx.EVT_LEFT_DCLICK( self.list, self.OnActivateAccount )
		self.var_list.Bind( wx.EVT_LIST_ITEM_SELECTED, self.OnVariableSelected )
		#self.var_list.Bind( wx.EVT_LIST_ITEM_ACTIVATED, self.OnVariableSelected )

		#~ self.p = wx.Panel( self.vSplitter, -1 )
		#~ self.Show()
		#~ self.Show( False )
		#text
		self.text_editor = editors.text( self )
		self.text_editor.Show( False )
		self.variable_editors.append( self.text_editor )
		#text/html
		self.texthtml_editor = editors.texthtml( self )
		self.texthtml_editor.Show( False )
		self.variable_editors.append( self.texthtml_editor )
		#choice
		self.choice_editor = editors.choice( self )
		self.choice_editor.Show( False )
		self.variable_editors.append( self.choice_editor )
		#number
		self.number_editor = editors.number( self )
		self.number_editor.Show( False )
		self.variable_editors.append( self.number_editor )
		#date
		self.date_editor = editors.date( self )
		self.date_editor.Show( False )
		self.variable_editors.append( self.date_editor )
		#frequency
		self.frequency_editor = editors.frequency( self )
		self.frequency_editor.Show( False )
		self.variable_editors.append( self.frequency_editor )
		# for contacts and groups, add the extra editors
		# runtime comparisson
		is_contact_class= ( str( self.__class__ ).find('sui.contacts.contact') > -1 )
		is_group_class	= ( str( self.__class__ ).find('sui.contacts.group') > -1 )
		if is_contact_class or is_group_class:
			# membership
			if is_contact_class:
				self.membership_editor = self.account.window.get_membership_editor( self.vSplitter, 'groups' )
				self.membership_editor.for_contact( self.rex_object )
			elif is_group_class:
				self.membership_editor = self.account.window.get_membership_editor( self.vSplitter, 'contacts' )
				self.membership_editor.for_group( self.rex_object )
			self.membership_editor.Show( False )
			self.variable_editors.append( self.membership_editor )
			# subscriptions
			self.subscription_editor = editors.subscription( self )
			self.subscription_editor.Show( False )
			self.variable_editors.append( self.subscription_editor )
			# block
			self.block_editor = editors.block( self )
			self.block_editor.Show( False )
			self.variable_editors.append( self.block_editor )
			# application
			self.application_editor = editors.application( self )
			self.application_editor.Show( False )
			self.variable_editors.append( self.application_editor )
			
		is_request_class	= ( str( self.__class__ ).find('sui.contacts.request') > -1 )	
		if is_request_class:
			self.membership_editor = self.account.window.get_membership_editor( self.vSplitter, 'processing queue' )
			self.membership_editor.for_request( self.rex_object )
			self.membership_editor.Show( False )
			self.variable_editors.append( self.membership_editor )
			#self.membership_editor.for_group( self.rex_object )
		is_survey_class= ( str( self.__class__ ).find('sui.forms.survey') > -1 )
		if is_survey_class:
			#self.email_editor = editors.survey_email( self )
			#self.email_editor.Show( False )
			#self.variable_editors.append( self.email_editor )
			#common.dprint("Created email editor")
			self.questions_editor = editors.questions_editor( self )
			self.questions_editor.Show( False )
			self.variable_editors.append( self.questions_editor )
			common.dprint("Created question editor ", self.questions_editor )
			self.notifiers_editor = editors.notifiers_editor( self )
			self.notifiers_editor.Show( False )
			self.variable_editors.append( self.notifiers_editor )
			common.dprint("Created question editor ", self.notifiers_editor )
		
		# split on the default editor
		self.vSplitter.SetMinimumPaneSize(20)
		self.vSplitter.SplitVertically( self.var_list, self.text_editor, self.sash_pos )
		self.vSplitter.SetSashPosition( self.sash_pos )
		# the find bar
		self.create_findbar()
		# Set the sizer and layout
		self.SetSizer( self.sizer )
		self.SetAutoLayout( 1 )
		# Windows needs this call
		self.Layout()
		self.Show()
		# Much showing and refreshing for OSX
		self.vSplitter.Show()
		self.vSplitter.Refresh()
		#self.create_help_and_about()
		self.account.window.SetStatusText( "Ready" )

	def create_toolbar( self ):
		# create a button bar
		self.button_bar = wx.BoxSizer( wx.HORIZONTAL )
		# add buttons to it
		self.save_button = wx.BitmapButton( self, -1, images.getSaveBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.save_button.Bind( wx.EVT_BUTTON, self.OnSave )
		self.button_bar.Add( self.save_button, 0 )
		# Upload file
		#~ self.upload_button = wx.Button( self, wx.ID_UP, style=wx.NO_BORDER )
		#~ self.upload_button.Bind( wx.EVT_BUTTON, self.OnUpload )
		#~ self.button_bar.Add( self.upload_button, 0 )
		# print button
		#~ self.print_button = wx.Button( self, wx.ID_PRINT, style=wx.NO_BORDER )
		#~ self.print_button.Bind( wx.EVT_BUTTON, self.OnPrint )
		#~ self.button_bar.Add( self.print_button, 0 )
		# preview button
		# only when the rex_object is an issue
		if isinstance( self.rex_object, rex.publications.issue ) or isinstance( self.rex_object, rex.dav.dav_item ):
			#preview button
			self.preview_button = wx.BitmapButton( self, -1, images.getPreviewBitmap(), size=common.button_size, style=wx.NO_BORDER )
			self.preview_button.Bind( wx.EVT_BUTTON, self.OnPreview )
			self.button_bar.Add( self.preview_button, 0 )
			#publish button
			if isinstance( self.rex_object, rex.publications.issue ):
				self.publish_button = wx.BitmapButton( self, -1, images.getPublishBitmap(), size=common.button_size, style=wx.NO_BORDER )
				self.publish_button.Bind( wx.EVT_BUTTON, self.OnPublish )
				self.button_bar.Add( self.publish_button, 0 )
		# texthtml dropdown
		self.texthtml_choice = wx.Choice( self, -1, choices=['Html','Text'], style=wx.NO_BORDER )
		self.texthtml_choice.SetSelection( 0 )
		self.texthtml_choice.Bind( wx.EVT_CHOICE, self.OnTextHtmlChanged )
		self.button_bar.Add( self.texthtml_choice, 0 )
		#script helper
		self.script_button = wx.BitmapButton( self, -1, images.getScriptHelperBitmap(), size=common.button_size, style = wx.NO_BORDER )
		self.script_button.Bind( wx.EVT_BUTTON, self.OnScriptHelper )
		self.button_bar.Add( self.script_button, 0 )
		# spacer
		self.button_bar.Add( (10,10), 1, wx.EXPAND )
		# zoom
		self.zoom_button = wx.BitmapButton( self, -1, images.getZoomBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.zoom_button.Bind( wx.EVT_BUTTON, self.OnZoom )
		self.button_bar.Add( self.zoom_button, 0 )
		self.close_button = wx.BitmapButton( self, -1, images.getCloseBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.close_button.Bind( wx.EVT_BUTTON, self.OnClose )
		self.button_bar.Add( self.close_button, 0 )
		# Add the button bar
		self.sizer.Add( self.button_bar, 0, wx.EXPAND )

	def create_findbar( self ):
		# create a button bar
		self.findbar	= wx.Panel( self )
		self.findsizer = wx.BoxSizer( wx.HORIZONTAL )
		# add the close button
		self.close_findbar_button = wx.BitmapButton( self.findbar, -1, images.getCloseBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.close_findbar_button.Bind( wx.EVT_BUTTON, self.hide_findbar )
		self.findsizer.Add( self.close_findbar_button, 0 )
		# find label
		self.findsizer.Add( wx.StaticText( self.findbar, -1, 'Find:'), 0, wx.ALIGN_CENTER )
		# find text
		self.find_text = wx.TextCtrl( self.findbar, -1, '', style=wx.TE_PROCESS_ENTER )
		self.find_text.Bind( wx.EVT_TEXT, self.find_text_changed )
		self.find_text.Bind( wx.EVT_KEY_DOWN, self.find_text_key_down )
		self.find_text.Bind( wx.EVT_TEXT_ENTER, self.find_next )
		self.findsizer.Add( self.find_text, 1, wx.EXPAND )
		# add the next button
		self.find_next_button = wx.BitmapButton( self.findbar, -1, images.getDownArrowBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.find_next_button.Bind( wx.EVT_BUTTON, self.find_next )
		self.findsizer.Add( self.find_next_button, 0 )
		# add the prev button
		self.find_prev_button = wx.BitmapButton( self.findbar, -1, images.getUpArrowBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.find_prev_button.Bind( wx.EVT_BUTTON, self.find_prev )
		self.findsizer.Add( self.find_prev_button, 0 )
		# add the case match button
		self.find_case_button = wx.BitmapButton( self.findbar, -1, images.getNoMatchCaseBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.find_case_button.Bind( wx.EVT_BUTTON, self.find_case )
		self.findsizer.Add( self.find_case_button, 0 )
		# Replace label
		self.findsizer.Add( wx.StaticText( self.findbar, -1, 'Replace:'), 0, wx.ALIGN_CENTER  )
		# replace text
		self.replace_text = wx.TextCtrl( self.findbar, -1, '')
		self.replace_text.Bind( wx.EVT_TEXT, self.replace_text_changed )
		self.findsizer.Add( self.replace_text, 1, wx.EXPAND )
		# replace all
		self.replace_all_button = wx.BitmapButton( self.findbar, -1, images.getReplaceAllBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.replace_all_button.Bind( wx.EVT_BUTTON, self.replace_all )
		self.findsizer.Add( self.replace_all_button, 0 )
		# replace selection
		self.replace_sel_button = wx.BitmapButton( self.findbar, -1, images.getReplaceSelectionBitmap(), size=common.button_size, style=wx.NO_BORDER )
		self.replace_sel_button.Bind( wx.EVT_BUTTON, self.replace_selection )
		self.findsizer.Add( self.replace_sel_button, 0 )
		# Layout
		self.findbar.SetSizer( self.findsizer )
		self.findsizer.Layout()
		# Add the findbar
		self.sizer.Add( self.findbar, 0, wx.EXPAND )
		# hide the findbar
		self.findbar.Show( False )
		# add the close timer
		# self.findbar_timer = wx.Timer( self )

	def find_text_key_down( self, event ):
		key = event.GetKeyCode()
		if key == wx.WXK_ESCAPE:
			self.findbar.Show( False )
			self.sizer.Layout()
			self.current_variable_editor.SetFocus()
		event.Skip()

	def findbar_has_focus( self ):
		has_focus = self.FindFocus()
		if self.find_text == has_focus: return True
		if self.find_next_button == has_focus: return True
		if self.find_prev_button == has_focus: return True
		if self.find_case_button == has_focus: return True
		if self.replace_text == has_focus: return True
		if self.replace_all_button == has_focus: return True
		if self.replace_sel_button == has_focus: return True
		return False

	def hide_findbar( self, event=None ):
		# reset the close button
		self.close_findbar_button.SetBitmapLabel( images.getCloseBitmap() )
		# do we really hide? if the event object is the close button, yes we do
		if event and event.GetEventObject() == self.close_findbar_button:
			self.findbar.Show( False )
			self.sizer.Layout()
			self.current_variable_editor.SetFocus()
			return
		# not the close button, does the bar have focus?
		if self.findbar_has_focus():
			# skip, try again later
			# self.findbar_timer.Start( common.findbar_close_interval, True )
			return
		# nope, really hide
		self.findbar.Show( False )
		self.sizer.Layout()
		self.current_variable_editor.SetFocus()

	def show_findbar( self, event=None ):
		self.findbar_init()
		self.findbar.Show()
		self.sizer.Layout()
		self.find_text.SetFocus()
		#self.findbar_timer.Start( common.findbar_close_interval, True )

	def findbar_init( self ):
		'''Initialize the findbar with common.finddata'''
		# text
		self.find_text.SetValue( common.finddata['text'] )
		# rtext
		self.replace_text.SetValue( common.finddata['rtext'] )
		# match case
		if common.finddata['case']:
			self.find_case_button.SetBitmapLabel( images.getMatchCaseBitmap() )
		else:
			self.find_case_button.SetBitmapLabel( images.getNoMatchCaseBitmap() )

	def find_next( self, event=None ):
		common.finddata['forward'] = True
		#self.findbar_timer.Start( common.findbar_close_interval, True )
		if self.current_variable_editor == self.text_editor or self.current_variable_editor == self.texthtml_editor:
			if self.current_variable_editor.OnFindReplace('find') >= 0:
				self.close_findbar_button.SetBitmapLabel( images.getCloseBitmap() )
			else:
				self.close_findbar_button.SetBitmapLabel( images.getRedCloseBitmap() )

	def find_prev( self, event=None ):
		common.finddata['forward'] = False
		#self.findbar_timer.Start( common.findbar_close_interval, True )
		if self.current_variable_editor == self.text_editor or self.current_variable_editor == self.texthtml_editor:
			if self.current_variable_editor.OnFindReplace('find') >= 0:
				self.close_findbar_button.SetBitmapLabel( images.getCloseBitmap() )
			else:
				self.close_findbar_button.SetBitmapLabel( images.getRedCloseBitmap() )

	def find_case( self, event=None ):
		#common.dprint("Toggle Find Case")
		common.finddata['case'] = not common.finddata['case']
		if common.finddata['case']:
			self.find_case_button.SetBitmapLabel( images.getMatchCaseBitmap() )
		else:
			self.find_case_button.SetBitmapLabel( images.getNoMatchCaseBitmap() )
		#self.findbar_timer.Start( common.findbar_close_interval, True )

	def replace_all( self, event=None ):
		#common.dprint("Replace All")
		common.finddata['forward'] = True
		common.finddata['all'] = True
		#self.findbar_timer.Start( common.findbar_close_interval, True )
		if self.current_variable_editor == self.text_editor or self.current_variable_editor == self.texthtml_editor:
			if self.current_variable_editor.OnFindReplace('replace'):
				self.close_findbar_button.SetBitmapLabel( images.getCloseBitmap() )
			else:
				self.close_findbar_button.SetBitmapLabel( images.getRedCloseBitmap() )

	def replace_selection( self, event=None ):
		#common.dprint("Replace Selection")
		common.finddata['forward'] = True
		common.finddata['all'] = False
		#self.findbar_timer.Start( common.findbar_close_interval, True )
		if self.current_variable_editor == self.text_editor or self.current_variable_editor == self.texthtml_editor:
			if self.current_variable_editor.OnFindReplace('replace'):
				self.close_findbar_button.SetBitmapLabel( images.getCloseBitmap() )
			else:
				self.close_findbar_button.SetBitmapLabel( images.getRedCloseBitmap() )

	def find_text_changed( self, event=None ):
		common.finddata['text'] = self.find_text.GetValue()

	def replace_text_changed( self, event=None ):
		common.finddata['rtext'] = self.replace_text.GetValue()

	def SetFocus( self ):
		wx.Panel.SetFocus( self )
		# focus on the current editor
		if self.current_variable_editor:
			self.current_variable_editor.SetFocus()

	def OnZoom( self, event ):
		if self.account.window: self.account.window.OnZoom( 1 )

	def OnUpload( self, event ):
		pass

	def OnPrint( self, event ):
		pass

	def OnSashChanged( self, event ):
		self.sash_pos = event.GetSashPosition()

	def get_dirty_vars( self ):
		"""Returns a list of var_ids that are dirty"""
		var_ids = []
		for var_id, var in self.variables.items():
			if var['dirty']:
				#print var['name'], 'is dirty'
				var_ids.append( var_id )
		self.dirty = ( len( var_ids ) > 0 )
		return var_ids

	def is_dirty( self ):
		return ( len( self.get_dirty_vars() ) > 0 )

	def OnClose( self, event ):
		# Confirm if we are dirty.
		if self.is_dirty():
			dlg = wx.MessageDialog( self,
								   "Changes made, Save Now?",
								   "Save Changes?",
								   wx.YES_NO | wx.CANCEL | wx.NO_DEFAULT | wx.ICON_QUESTION )
			res = dlg.ShowModal()
			if res == wx.ID_CANCEL: return False
			if res == wx.ID_YES:	self.OnSave( None )
		# remove from the ebook
		if self.account and self.account.window:
			self.account.window.ebook.RemovePage( common.get_page_index( self.account.window.ebook, self ) )
			# do we need to unzoom
			if self.account.window.ebook.GetPageCount() < 1: self.account.window.zoom_out()
			self.account.window.ebook.Refresh()
		del self.account
		self.rex_object.editor = None
		del self.rex_object
		del self.treeitem
		self.Destroy()
		return True

	def load_rex_object( self ):
		if self.rex_object is None: return		
		for variable in self.rex_object.data:
			# don't add id and instance_id variables
			ignore = ['id', 'instance_id', 'trashed_on', 'licenses']
			if variable['name'].lower() in ignore:
				continue
			self.append_variable( variable )
		wx.Yield()
		if self.rex_object.__class__ != rex.dav.dav_item:
			#common.dprint("Sorting variables**")
			#if self.rex_object.module.lower() == 'survey' or  self.rex_object.module.lower() == 'referral' or
			#	self.rex_object: return
			if self.rex_object.__class__ == rex.contacts.contact or self.rex_object.__class__ == rex.binders.instance:
				self.var_list.SortItems( self.sort_variables )
				self.color_variables()
			# Reposition the splitter
			self.sash_pos = self.var_list.GetColumnWidth( 0 ) + 20
			#common.dprint( "The new sash position is", self.sash_pos )
			self.vSplitter.SetSashPosition( self.sash_pos )
		else:
			#self.vSplitter.GetWindow1().Show(False)
			#self.vSplitter.SetSashPosition( 0 )
			self.vSplitter.Unsplit( self.vSplitter.GetWindow1() )

	def append_variable( self, variable ):
		# Skip some variables
		# common.dprint("Name", variable['name'])
# 		common.dprint("Value", variable['value'])
# 		common.dprint("Type", variable['type'])
# 		common.dprint("\n")
		if variable['name']=='__eas__modtime': return
		if self.rex_object.__class__ != rex.dav.dav_item:
			if self.rex_object.module.lower() == 'web':
				skip = ['reply_email','cc_email','bcc_email','bouncer','bouncer_group','bouncer_email',
						'delivery', 'delivery_day', 'delivery_date','status','recurrence_rule',
						'recurrence_variable','archived_on']
				if variable['name'] in skip: return
			if self.rex_object.module.lower() == 'survey':
				skip = ['reply_email','cc_email','bcc_email','bouncer','bouncer_group','bouncer_email',
						'email_subject','email_body','email_address','email_html', 
						'r_comment_field', 'intro','intro_html', 'r_show_prompt', 'r_intro','r_intro_html',
						'r_email_subject','r_email_body','r_email_html', 'show_welcome','t_send_email',
						'f_email_subject','f_email_body','f_email_html',
						't_email_subject','t_email_body','t_email_html'  ]
				if variable['name'] in skip: return
				if self.rex_object.__class__ == rex.forms.survey:
					skip = ['header','footer']
					if variable['name'] in skip: return	
			if self.rex_object.module.lower() == 'referral':
				skip = ['reply_email','cc_email','bcc_email','bouncer','bouncer_group','bouncer_email',
						'email_subject','email_body','email_address', 'email_html',
						'intro','intro_html', 'r_show_prompt', 'sensitive', 'show_welcome',
						'referral_link', 'questions']
				if variable['name'] in skip: return
				if self.rex_object.__class__ == rex.forms.survey:
					skip = ['header','footer']
					if variable['name'] in skip: return	
		#common.dprint("Adding variable: ", variable['name'] )
		# make a copy of the variable locally to use as the working copy.
		# when the saving, we copy from these variables to the object.
		var = copy.deepcopy( variable )
		var['dirty'] = False
		var_id = abs( id( var ) )
		#print "adding variable: ", var, var_id
		#print "\n"
		#item = self.var_list.InsertStringItem( sys.maxint, var['label'] )
		item = self.var_list.InsertStringItem( len(self.variables), var['label'] )
		self.var_list.SetItemData( item, var_id )
		self.var_list.SetColumnWidth( 0, wx.LIST_AUTOSIZE )
		self.variables[ var_id ] = var
		# Select the id by default
		if 	var['name'] == 'header' and isinstance( self.rex_object, rex.publications.publication ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif 	var['name'] == 'content' and isinstance( self.rex_object, rex.publications.issue ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif var['name'] == 'first_name' and isinstance( self.rex_object, rex.contacts.contact ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif var['name'] == 'memberships' and isinstance( self.rex_object, rex.contacts.group ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif var['name'] == 'instance_name' and isinstance( self.rex_object, rex.binders.instance ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif var['name'] == 'body' and isinstance( self.rex_object, rex.dav.dav_item ):
			self.var_list.Select( item )
			#self.var_list.Focus( item )
		elif var['name'] == 'id':
			self.var_list.Select( item )
			#self.var_list.Focus( item )

	def sort_variables( self, v1, v2 ):
		var1 = self.variables[ v1 ]
		var2 = self.variables[ v2 ]
		#common.dprint( var1, var2 )
		#if self.rex_object.__class__ != rex.forms.form and self.rex_object.__class__ != rex.forms.survey and self.rex_object.__class__ != rex.forms.referral:
		# if they are not custom variables, leave them alone
		if var1['custom'] == False and var2['custom'] == False:
			return 0
		# var2 is custom
		elif var1['custom'] == False and var2['custom'] == True:
			# var1 wins
			return -1
		elif var1['custom'] == True and var2['custom'] == False:
			# var2 wins
			return 1
	# Now, if both are custom, sort on the variable name
		if var1['name'] > var2['name']:
			# var1 wins
			return 1
		if var1['name'] < var2['name']:
			# var2 wins
			return -1
		# otherwise they are the same, which could never happen
		#common.dprint( var1, var2 )
		return 0

	def color_variables( self ):
		#loop through the list items
		count = self.var_list.GetItemCount()
		if count < 1:
			common.dprint("No variables to colorize")
			return
		for i in range( 0, count ):
			var_id = self.var_list.GetItemData( i )
			var = self.variables[ var_id ]
			item = self.var_list.GetItem( i )
			if var['custom']:
				item.SetTextColour( wx.BLUE )
				self.var_list.SetItem( item )
			else:
				item.SetBackgroundColour( common.sui_colors('whitesmoke') )
				self.var_list.SetItem( item )

	def OnTextHtmlChanged( self, event = None ):
		# Switch the values being shown
		if self.current_variable_editor is None: return
		if self.current_variable_editor.__class__ != self.texthtml_editor.__class__: return
		self.switching = True
		try:
			var_id = self.current_variable_editor.var_id
			var = self.variables[ var_id ]
			self.current_variable_editor.set_value( var['value'] )
		except:
			common.show_error( "Failed to switch Text/Html" )
		self.switching = False

	def get_texthtml( self ):
		#ret = ( self.texthtml_choice.GetStringSelection() == 'Html' )
		#print "current texthtml value is ", self.texthtml_choice.GetStringSelection(), ret
		return ( self.texthtml_choice.GetStringSelection() == 'Html' )

	def set_texthtml( self, html ):
		if self.current_variable_editor is None: return
		if self.current_variable_editor.__class__ != self.texthtml_editor.__class__: return
		if html:
			self.texthtml_choice.SetSelection( 0 )
		else:
			self.texthtml_choice.SetSelection( 1 )
		self.OnTextHtmlChanged()

	def toggle_texthtml( self ):
		if self.current_variable_editor is None: return
		if self.current_variable_editor.__class__ != self.texthtml_editor.__class__: return
		self.set_texthtml( not self.get_texthtml() )

	def select_next_variable( self ):
		sel = common.get_selected_in_list( self.var_list )
		if not sel or len( sel ) == 0: return
		# adjust the 0-index to a position index starting at 1
		pos = sel[0] + 1
		# get the count
		count = self.var_list.GetItemCount()
		# are we at the end? do nothing
		if pos == count: return
		# otherwise, select the next variable
		# pos = pos + 1
		# we don't need to increment here, since the pos was adjusted +1 before already
		self.var_list.Select( pos )
		# give the focus back to the editor
		self.current_variable_editor.SetFocus()

	def select_prev_variable( self ):
		sel = common.get_selected_in_list( self.var_list )
		if not sel or len( sel ) == 0: return
		# adjust the 0-index to a position index starting at 1
		pos = sel[0] + 1
		# are we at the end? do nothing
		if pos == 1: return
		# otherwise, select the previous variable
		pos = pos - 1
		self.var_list.Select( pos )
		# give the focus back to the editor
		self.current_variable_editor.SetFocus()

	def OnVariableSelected( self, event ):
		# Load up the variable data onto the variable editor
		sel = common.get_selected_in_list( self.var_list )
		var_id = self.var_list.GetItemData( sel[0] )
		#print "selected id:", var_id
		var = self.variables[ var_id ]
		self.switching = True	# So we don't set off alarms about modification
		# switch to the editor type
		self.current_variable_editor = self.select_variable_editor( var )
		for ve in self.variable_editors:
			ve.Show( ( self.current_variable_editor.__class__ == ve.__class__ ) )
		# show/hide the text html choice
		self.texthtml_choice.Show( self.current_variable_editor.__class__ == self.texthtml_editor.__class__ )
		# much splitting, refreshing, and showing for OSX
		self.vSplitter.Unsplit()
		self.vSplitter.SplitVertically( self.var_list, self.current_variable_editor, self.sash_pos )
		self.current_variable_editor.Show()
		self.vSplitter.Show()
		self.vSplitter.Refresh()
		if self.rex_object.__class__ == rex.forms.survey and var['name'] == 'questions':
			self.current_variable_editor.set_value( self.rex_object.questions )
		elif self.rex_object.__class__ == rex.forms.survey and var['name'] == 'notifiers':
			self.current_variable_editor.set_value( self.rex_object.notifiers )
		else:
			self.current_variable_editor.set_value( var['value'] )
		self.current_variable_editor.set_readwrite( var['rw'] )
		self.current_variable_editor.var_id = var_id
		self.switching = False
		
	def select_variable_editor( self, var ):
		if var['type'] == rex.base.ROT_TEXT:
			# is it a custom + file value? show the file uploader instead
			return self.text_editor
		if var['type'] == rex.base.ROT_NUMBER:
			if ( var['rw'] ) and ( var['name'] != 'publication_id' ):
				return self.number_editor
			else:
				return self.text_editor
		if var['type'] == rex.base.ROT_CHOICE:
			self.choice_editor.set_options( var['options'] )
			return self.choice_editor
		if var['type'] == rex.base.ROT_DATE:
			return self.date_editor
		if var['type'] == rex.base.ROT_FREQ:
			return self.frequency_editor
		if var['type'] == rex.base.ROT_TEXTHTML:
			return self.texthtml_editor
		if var['type'] == rex.base.ROT_MEMBERSHIP:
			return self.membership_editor
		if var['type'] == rex.base.ROT_SUBS:
			return self.subscription_editor
		if var['type'] == rex.base.ROT_BLOCKS:
			return self.block_editor
		if var['type'] == rex.base.ROT_INS:
			return self.application_editor
		if var['type'] == rex.base.ROT_QUESTIONS:
			return self.questions_editor
		#if var['type'] == rex.base.ROT_EMAIL:
		#	return self.email_editor
		if var['type'] == rex.base.ROT_NOTIFIERS:
			return self.notifiers_editor
		return None

	def set_var_dirty( self, var_id ):
		if self.switching:
			return
		#try:
		#	common.dprint( "setting   var_id[ %s ] dirty" % var_id )
		#	common.dprint( "setting var_name[ %s ] dirty" % self.variables[ var_id ]['name'] )
		#except:
		#	pass
		if var_id:
			self.variables[ var_id ]['dirty'] = True
			if self.variables[ var_id ]['type'] == rex.base.ROT_TEXTHTML:
				if self.get_texthtml():
					self.variables[ var_id ]['value'][1] = unicode( self.current_variable_editor.get_value() )
				else:
					self.variables[ var_id ]['value'][0] = unicode( self.current_variable_editor.get_value() )
			else:
				self.variables[ var_id ]['value'] = unicode( self.current_variable_editor.get_value() )
		else:
			self.dirty = True
		#if not self.dirty:
		self.ResetTitle()

	def OnTimer( self, event ):
#		'''Resets the status bar text back to "Ready"'''
#		if event.GetEventObject() == self.findbar_timer:
#			self.hide_findbar()
#			return
		self.account.window.SetStatusText( "Ready" )

	def get_label_text( self ):
		dirty  = ''
		if self.is_dirty() or self.dirty: dirty = '*'
		if self.rex_object.__class__ == rex.binders.instance:
			label = "%s.%s%s" %( self.rex_object.binder['id'], self.rex_object['instance_id'], dirty )
		elif self.rex_object.__class__ == rex.dav.dav_item:
			label = "%s%s" %( self.rex_object['name'], dirty )
		else:
			label = "%s%s" %( self.rex_object['id'], dirty )
		return label

	def OnSave( self, event=None ):
		cur = wx.BusyCursor()
		self.account.window.SetStatusText( "Saving, please wait..." )
		wx.Yield()
		# transfer to the rex object
		var_ids = self.get_dirty_vars()
		saving_name = False
		newname = 0
		if len( var_ids ) > 0:
			if self.rex_object.__class__ != rex.dav.dav_item:
				for var_id in var_ids:
					var = self.variables[ var_id ]
					#print "transfering", var['name']
					self.rex_object[ var['name'] ] = copy.deepcopy( var['value'] )
					if re.compile( 'name', re.IGNORECASE ).match( var['name'] ) :
						newname = var['value']
						saving_name = True
				try:
					#print "Saving"
					self.rex_object.save()
					self.rex_object.set_clean()
					for var_id in var_ids:
						self.variables[ var_id ]['dirty'] = False
					self.dirty = False
				except:
					common.show_error( "Failed to save" )
			else:
				try:
					var_id = var_ids[0]
					var = self.variables[ var_id ]
					self.davCon.put_file( self.rex_object.uri, var['value'] )
					self.variables[ var_id ]['dirty'] = False
				except:
					common.show_error( "Failed to save dav" )
		del cur
		self.account.window.SetStatusText( "Ready" )
		self.ResetTitle()
		if self.parent_tree and saving_name :
			common.dprint( "Name was saved.  Refreshing the publication list." )
			self.parent_tree.tree.SetItemText( self.treeitem, newname, 1 )
			self.parent_tree.Refresh()

	def OnDelete( self, event ):
		# Call the parent window to destroy this object
		if self.rex_object.object_name == "publication":
			self.GetParent().OnPublicationDelete( event )
		elif self.rex_object.object_name == "issue":
			self.GetParent().OnIssueDelete( event )
		elif self.rex_object.object_name == "form":
			self.GetParent().OnFormDelete( event )
		elif self.rex_object.object_name == "survey":
			self.GetParent().OnSurveyDelete( event )
		elif self.rex_object.object_name == "instance":
			self.GetParent().OnInstanceDelete( event )

	def ResetTitle( self ):
		# Set the Tab Title
		title = self.get_label_text()
		pindex = common.get_page_index( self.GetParent(), self.rex_object.editor )
		if pindex >= 0: self.GetParent().SetPageText( pindex, title )

	def OnKeyDown( self, event ):
		# check for the zoomers
		pass

	def OnPreview( self, event ):
		if not ( isinstance( self.rex_object, rex.publications.issue ) or isinstance( self.rex_object, rex.dav.dav_item ) ): return
		# check if there is a designated contact.
		common.dprint("designated uuid", self.account.window.designated_contact_uuid )
		if not self.account.window.designated_contact_uuid or len( str(self.account.window.designated_contact_uuid) ) < 32:
			dlg = wx.MessageDialog( self, "No contact is designated for preview.\n Please designate a contact.", "Preview", wx.OK )
			common.metalic(dlg)
			icon = icon_manager.get_icon( "ESM" )
			dlg.SetIcon( icon )
			dlg.ShowModal()
			dlg.Destroy()
			dlg = None
			return
		url = ''
		s = ''
		if self.account.secure: s = "s"
		if isinstance( self.rex_object, rex.dav.dav_item ):
			url = "http://%s%s?cid=%s" % \
				( self.account.server,
					self.rex_object.uri,
				  self.account.window.designated_contact_uuid,
				)
		else:
			url = "http://%s/sys/nl/ai.esp?cid=%s&iid=%s" % \
				( self.account.server,
				  self.account.window.designated_contact_uuid,
				  self.rex_object['id']
				)
		common.dprint("Opening URL", url )
		webbrowser.open( url )
		
	def OnScriptHelper( self, evt ):
		if isinstance( self.current_variable_editor, editors.text ) :
			common.dprint( "in a text editor" )
			self.current_variable_editor.ShowScriptHelper( )
		else :
			common.dprint( "not in a text editor" )
